<script lang="js" setup name="Displayer">
import { ref, reactive, onMounted, onActivated, computed, watch, onBeforeUnmount, getCurrentInstance } from "vue";
import { useArchiveStore } from "../stores/archive";
import { useAppStore } from "../stores/appStore";
import { RenderingEngine, getRenderingEngine, Enums, metaData, utilities as csUtils } from '@cornerstonejs/core';
import { toolGroup, removeViewportMeasures, addImageSliceSync } from "../cornerstone3D/initTools";
import getOrientationMarkers from "../cornerstone3D/orientText";
import VerticalScrollbar from "./VerticalScrollbar.vue";
import Playbar from "./Playbar.vue";
import { renderingEngineId2d } from "../cornerstone3D";
import XMenu from "./XMenu/XMenu.vue";

const { worldToImageCoords, imageToWorldCoords } = csUtils;
const { proxy } = getCurrentInstance();
const { ViewportType } = Enums;
const { IMAGE_RENDERED, CAMERA_MODIFIED, STACK_VIEWPORT_SCROLL, STACK_NEW_IMAGE, VOI_MODIFIED } = Enums.Events;

const archiveData = useArchiveStore();
const appStore = useAppStore();

const emit = defineEmits(["selected"]);

const displayer = ref(null);
const scrollbar = ref(null);
const playbar = ref(null);
const IsSel = ref(false);
const IsHover = ref(false);
const showPlaybar = ref(false);

const xMenu = ref(null);

const state = reactive({
    series: null,
    image: null,
    imageIds: [],
    isSeries: false,
    viewport: null,
    renderingEngine: null,
    stackIndex: -1,
    preStackIndex: -1,
});


const props = defineProps({
    pos: {
        type: Number,
        required: true,
    },
});


const viewportId = `DISP_STACK_${props.pos}`;

const borderClass = computed(() => {
    let s = "selected";
    if (IsSel.value) {
        s = "selected";
    } else {
        if (IsHover.value) {
            s = "hovered";
        } else {
            s = "unselect";
        }
    }
    return s;

});

const orientation = reactive({
    top: "",
    bottom: "",
    left: "",
    right: "",
});

const canShowPlaybar = computed(() => {
    return state.isSeries && state.series && state.series.GetCount() > 1;
});


const minPos = ref(0);
const maxPos = computed(() => {
    return state.imageIds.length - 1;
});


watch(() => appStore.showCornerText, (newVal, oldVal) => {
    if (state.series)
        state.viewport.render();
});

watch(() => appStore.showOverlay, (newVal, oldVal) => {
    if (state.series)
        state.viewport.render();
});


const dragDrop = (e) => {
    // e.preventDefault();
    const seriesInsUid = e.dataTransfer.getData("seriesInsUid");
    // console.log("dragDrop:", seriesInsUid);
    const series = archiveData.currentStudy.FindSeries(seriesInsUid);
    if (series) {
        // console.log("dragDrop:", series);
        load(series, 0, true);
    }
};

// 移动端触摸拖放支持
const handleTouchStart = (e) => {
    // 记录触摸开始，用于后续的拖放检测
    e.currentTarget._touchStart = {
        x: e.touches[0].clientX,
        y: e.touches[0].clientY,
        time: Date.now()
    };
};

const handleTouchMove = (e) => {
    // 允许拖放操作，不阻止默认行为
    // e.preventDefault();
};

const handleTouchEnd = (e) => {
    const touchStart = e.currentTarget._touchStart;
    if (touchStart) {
        const touch = e.changedTouches[0];
        const deltaX = Math.abs(touch.clientX - touchStart.x);
        const deltaY = Math.abs(touch.clientY - touchStart.y);
        const deltaTime = Date.now() - touchStart.time;

        // 如果是快速点击且移动距离小，认为是点击而不是拖放
        if (deltaTime < 300 && deltaX < 10 && deltaY < 10) {
            // 这是点击事件，不是拖放
            onMouseDown();
        }

        delete e.currentTarget._touchStart;
    }
};

const onMouseDown = () => {
    IsSel.value = true;
    emit("selected", { pos: props.pos });
};

const onMouseOver = () => {
    IsHover.value = true;
};

const onMouseOut = () => {
    IsHover.value = false;
};

const onMouseUp = () => {
    // IsSel.value = false;
};

const mouseMove = (e) => {
    const curPt = { x: e.offsetX, y: e.offsetY };

    if (e.target.className.includes("orient_bottom")) {
        curPt.y += e.target.offsetTop;
    }


    if (canShowPlaybar && maxPos.value > 1) {
        // showPlaybar.value = false;
        const rect = displayer.value.getBoundingClientRect();
        // console.log("rect:", rect);
        if (curPt.y > rect.height - 52 && curPt.y < rect.height-20) {
            showPlaybar.value = true;
        } else {
            showPlaybar.value = false;
        }
    }
};

const mouseOutPlaybar = () => {
    showPlaybar.value = false;
};


const setSelected = (selected) => {
    IsSel.value = selected;
};

let resizeTimeout = null;
const resizeObserver = new ResizeObserver((entries) => {
    if (resizeTimeout) {
        return;
    }
    resizeTimeout = setTimeout(resize, 100);
    // resize();
});

const resize = () => {
    resizeTimeout = null;
    if (!isLoaded()) return;
    const presentations = state.viewport.getViewPresentation();
    state.renderingEngine.resize(true, false);
    state.viewport.setViewPresentation(presentations);
};


const init = () => {
    // console.log("init viewportId", viewportId);
    const viewportInput = {
        viewportId,
        type: ViewportType.STACK,
        // type,
        element: displayer.value,
        defaultOptions: {
            background: [0, 0, 0],
            // cursor: "pointer",
        },
    };

    state.renderingEngine = getRenderingEngine(renderingEngineId2d);
    if (!state.renderingEngine) {
        state.renderingEngine = new RenderingEngine(renderingEngineId2d);
        console.log("created new renderingEngine", renderingEngineId2d);
    }

    state.renderingEngine.enableElement(viewportInput);
    state.viewport = state.renderingEngine.getViewport(viewportId);
    // toolGroup.addViewport(viewportId, renderingEngineId2d);

    // console.log("init viewportId", viewportId, state.viewport);

};

const load = (series, idx, isSeries) => {
    if (!series) return;
    // console.log("load", viewportId);

    clear();

    state.image = series.GetImageByIndex(idx);
    if (!state.image) return;
    state.series = series;
    state.isSeries = isSeries;

    if (state.image.numberOfFrames > 1) {
        state.isSeries = false;
    }

    if (state.isSeries) {
        state.imageIds = series.GetImageIds();
    } else {
        if (state.image.numberOfFrames > 1) {
            state.imageIds = state.image.frameIds;
        } else {
            state.imageIds.push(state.image.imageId);
        }
    }

    init();

    toolGroup.addViewport(viewportId, renderingEngineId2d);
    if (appStore.syncOperation.syncRoll) {
        addImageSliceSync(viewportId);
    }

    state.viewport.setStack(state.imageIds);
    state.viewport.render();

}

const onImageRendered = (event) => {
    if (!state.series) return;
    // console.log("onImageRendered", event);

    const imageId = state.viewport.getCurrentImageId();
    state.image = state.series.GetImageById(imageId);

    // 2025.05.18 显示overlay
    const overlayPlaneModule = metaData.get("overlayPlaneModule", imageId);
    if (overlayPlaneModule) {
        const { overlays } = metaData.get("overlayPlaneModule", imageId);
        // console.log("onImageRendered overlays:", overlays);

        if (appStore.showOverlay && overlays.length > 0) {
            drawOverlay(overlays[0]);
        }
    }

    if (appStore.showCornerText) {
        drawText();
    }

    drawRuler();
};

const drawText = () => {
    const canvas = displayer.value.querySelector(".cornerstone-canvas");
    const context = canvas.getContext("2d");
    const cvs_w = canvas.width;  // 使用canvas的实际尺寸
    const cvs_h = canvas.height; // 使用canvas的实际尺寸

    const mtx = context.getTransform();
    context.resetTransform();

    context.font = "14px Arial";
    context.fillStyle = "white";
    context.textAlign = "left";
    context.textBaseline = "top";

    const idx = state.viewport.getCurrentImageIdIndex();
    const image = state.image;

    let x = 5;
    let y = 5;
    let h = 17;
    let val;

    // 左上角 left-top
    // 姓名
    val = image.PatientName;
    context.fillText(val, x, y);
    y += h;
    // PatientId
    val = image.PatientID;
    context.fillText(val, x, y);
    y += h;
    // 年龄(或者生日)+性别
    val = image.AgeAndSex;
    if (val) {
        context.fillText(val, x, y);
        y += h;
    }
    // Image Comments
    val = image.ImageComments;
    if (val) {
        context.fillText(val, x, y);
        y += h;
    }

    // 左下角 left-bottom
    y = cvs_h - h;
    // 医院名
    val = image.HospitalName;
    if (val) {
        context.fillText(val, x, y);
        y -= h;
    }
    // 序列时间
    // val = "序列时间:" + image.SeriesDateTime;
    // if (val) {
    //     context.fillText(val, x, y);
    //     y -= h;
    // }
    // 图像时间
    // const dateStr = image.AcquisitionDate;
    // const timeStr = image.AcquisitionTime;
    val = image.ContentDate + " " + image.ContentTime;
    if (val) {
        context.fillText(val, x, y);
        y -= h;
    }
    // Study Date
    // val = image.StudyDate;
    // if (val) {
    //     context.fillText(val, x, y);
    //     y -= h;
    // }
    // Study Description
    val = image.StudyDesc;
    if (val) {
        context.fillText(val, x, y);
        y -= h;
    }
    //series Description
    // val = "序列描述:" + image.SeriesDesc;
    val = image.SeriesDesc;
    if (val) {
        context.fillText(val, x, y);
        y -= h;
    }
    //患者方向
    val = image.PatientPosition;
    if (val) {
        context.fillText(val, x, y);
        y -= h;
    }

    // 右上角 right-top
    const rmargin = 5;
    y = 5;
    const range = state.viewport.getProperties().voiRange || {lower: -1024, upper: 1024};
	const wwwl = csUtils.windowLevel.toWindowLevel(range.lower, range.upper);
    val = "WL:" + wwwl.windowCenter.toFixed(0);
    val += " WW:" + wwwl.windowWidth.toFixed(0);
    x = cvs_w - rmargin - context.measureText(val).width;
    context.fillText(val, x, y);
    y += h;
    // Image No-Count
    const prefix = image.numberOfFrames>1 ? "Fr:" : "Im:";
    val = prefix + (idx + 1) + "/" + (maxPos.value + 1);
    x = cvs_w - rmargin - context.measureText(val).width;
    context.fillText(val, x, y);
    y += h;
    // Series No
    val = image.SeriesNo;
    if (val) {
        x = cvs_w - rmargin - context.measureText(val).width;
        context.fillText(val, x, y);
        y += h;
    }
    // modality
    val = image.DeviceName;
    if (val) {
        x = cvs_w - rmargin - context.measureText(val).width;
        context.fillText(val, x, y);
    }

    // 右下角 right-bottom
    y = cvs_h - h;
    // Thickness-Location
    val = image.ThicknessLocation;
    if (val) {
        x = cvs_w - rmargin - context.measureText(val).width;
        context.fillText(val, x, y);
        y -= h;
    }

    // 曝光参数
    val = image.Exposure;
    if (val) {
        x = cvs_w - rmargin - context.measureText(val).width;
        context.fillText(val, x, y);
        y -= h;
    }
    // 拍片参数
    val = image.TrTe;
    if (val) {
        x = cvs_w - rmargin - context.measureText(val).width;
        context.fillText(val, x, y);
        y -= h;
    }
    // Zoom
    const imageData = state.viewport.getImageData();
    const camera = state.viewport.getCamera();
    let spacing = [1, 1, 1];
    if (imageData) {
      spacing = imageData.spacing;
    }
    const t = cvs_h * spacing[1] * 0.5;
    const scale = t / camera.parallelScale;
    val = "Zoom:" + scale.toFixed(2);
    x = cvs_w - rmargin - context.measureText(val).width;
    context.fillText(val, x, y);

    context.setTransform(mtx);
}

const drawRuler = () => {
    const canvas = displayer.value.querySelector(".cornerstone-canvas");
    const context = canvas.getContext("2d");
    const cvs_w = canvas.width;
    const cvs_h = canvas.height;
    const minHW = Math.min(cvs_w, cvs_h);

    const image = state.image;
    const { ps_col, ps_row } = image;

    if (!ps_col || !ps_row) {
        // console.log("no ps_col or ps_row");
        return;
    }

    const color = "lightgreen";
    context.font = "14px Arial";
    context.fillStyle = color;
    context.textAlign = "left";
    context.textBaseline = "top";

    let fontSize = 12; //字体大小
    let tickSize = 4;  //刻度宽度

    if (minHW > 1199) {
        fontSize = 19;
        tickSize = 7;
    } else if (minHW > 799) {
        fontSize = 17;
        tickSize = 6;
    } else if (minHW > 399) {
        fontSize = 14;
        tickSize = 5;
    } else if (minHW > 199) {
        fontSize = 12;
        tickSize = 4;
    } else {
        fontSize = 8;
        tickSize = 4;
    }

    context.font = fontSize + "px Arial";
    const scale = getScale();
    const { ruler, unit } = getRuler(ps_col, cvs_h, scale);
    const txt = "" + ruler;
    const txtSize = context.measureText(txt);

    //标尺长度换算成像素
    const t = unit === "cm" ? 10 : 1;
    const oneTick = ((ruler * t) / ps_row) * scale;

    //垂直标尺 - 放在最右边居中
    let margin = 10; // 固定边距
    let ptV_s = {
        x: 0,
        y: 0
    };
    let ptV_e = {
        x: 0,
        y: 0
    };
    let ptCenter = {
        x: 0,
        y: 0
    };
    ptCenter.x = cvs_w - margin;
    ptCenter.y = cvs_h / 2;
    ptV_s.x = ptV_e.x = cvs_w - margin;
    ptV_s.y = ptCenter.y - oneTick / 2;
    ptV_e.y = ptV_s.y + oneTick;
    context.beginPath();
    context.lineWidth = 1;
    context.strokeStyle = color;
    context.moveTo(ptV_s.x, ptV_s.y);
    context.lineTo(ptV_e.x, ptV_e.y);
    for (let i = 0; i <= ruler; i++) {
        let x, y, xe;
        x = ptV_s.x;
        y = ptV_s.y + (i * oneTick) / ruler;
        if (i % 5 == 0) {
            xe = x - tickSize*2;
        } else {
            xe = x - tickSize;
        }
        context.moveTo(x, y);
        context.lineTo(xe, y);
    }
    context.stroke();
    const x = ptV_e.x + tickSize; // 标尺右侧显示文字
    const y = ptV_e.y + tickSize;
    context.fillText(txt, x, y);
    context.fillText(unit, x, y + fontSize);
};

const drawOverlay = (overlay) => {
    const dcm = state.image;
    const canvas = displayer.value.querySelector(".cornerstone-canvas");
    const context = canvas.getContext("2d", { willReadFrequently:true });

    const cvs_w = canvas.width;
    const cvs_h = canvas.height;

    // console.log('drawOverlay canvas', cvs_w, cvs_h, context.canvas.width, context.canvas.height);

    const imageData = context.getImageData(
				0,
				0,
				cvs_w,
				cvs_h,
                { willReadFrequently:true }
			);
	const { data } = imageData;

    const bits = 16;
    const imageId = state.viewport.getCurrentImageId();

    let dirtyX = Infinity;
    let dirtyY = Infinity;
    let dirtyX2 = -Infinity;
    let dirtyY2 = -Infinity;

    for (let y = 0; y < overlay.rows; y++) {
        for (let x = 0; x < overlay.columns; x++) {
            const val = overlay.pixelData[y * overlay.columns + x];
            if (val === 0) continue;

            const worldPos = imageToWorldCoords(imageId, [x, y]);
            const canvasPos = state.viewport.worldToCanvas(worldPos);
            canvasPos[0] = Math.floor(canvasPos[0]);
            canvasPos[1] = Math.floor(canvasPos[1]);

            if (canvasPos[0] < 0 || canvasPos[0] >= cvs_w || canvasPos[1] < 0 || canvasPos[1] >= cvs_h) {
                continue;
            }

            const idx = canvasPos[0] * 4 + canvasPos[1] * cvs_w * 4;

            if (idx>=0 && idx < data.length) {
                dirtyX = Math.min(canvasPos[0], dirtyX);
                dirtyY = Math.min(canvasPos[1], dirtyY);
                dirtyX2 = Math.max(canvasPos[0], dirtyX2);
                dirtyY2 = Math.max(canvasPos[1], dirtyY2);
                data[idx] = 234;
                data[idx + 1] = 234;
                data[idx + 2] = 184;
            }
        }
    }

    context.putImageData(imageData, 0, 0, dirtyX, dirtyY, dirtyX2 - dirtyX + 1, dirtyY2 - dirtyY + 1);

};

const getRuler = (ps, cvs_h, scale) => {
    let ruler = 10;
    let unit = "cm";

    const minH = cvs_h * 0.25;
    const maxH = cvs_h * 0.85;

    const rulers = [5, 10, 25, 50, 100, 250, 500, 1000];

    for (let i = 0; i < rulers.length; i++) {
        const rulerMM = rulers[i];
        const rulerH = rulerMM / ps * scale;
        if (rulerH > minH && rulerH < maxH) {
            ruler = rulerMM;
            unit = "mm";
            if (rulerMM >= 50) {
                ruler = rulerMM / 10;
                unit = "cm";
            }
            break;
        } else {
            continue;
        }
    }

    return {
        ruler,
        unit
    };
}

const getScale = () => {
    const canvas = displayer.value.querySelector(".cornerstone-canvas");
    const cvs_h = canvas.clientHeight;
    const imageData = state.viewport.getImageData();
    const camera = state.viewport.getCamera();
    let spacing = [1, 1, 1];
    if (imageData) {
      spacing = imageData.spacing;
    }
    const t = cvs_h * spacing[1] * 0.5;
    const scale = t / camera.parallelScale;
    return scale;
}

const scrollTo = (pos) => {
    // console.log("scrollTo", pos, "minPos", minPos.value, "maxPos", maxPos.value);
    const idx = state.viewport.getCurrentImageIdIndex();
    const delta = pos - idx;
    state.viewport.scroll(delta);
};

const startPlay = () => {
    proxy.emitter.emit("stopAutoPlay", { pos: props.pos });
};

const onCameraModified = (event) => {
    if (!state.series) return;
    const { camera, previousCamera, rotation } = event.detail;
    // console.log("onCameraModified", event);
    const markers = getOrientationMarkers({
        image: state.image,
        camera,
        rotation,
    });
    orientation.top = markers.top;
    orientation.bottom = markers.bottom;
    orientation.left = markers.left;
    orientation.right = markers.right;

    if (!appStore.currentDisplayer) return;
    const isCurrent = (appStore.currentDisplayer.getViewportId() === viewportId);
    if (isCurrent && appStore.syncOperation.syncZoom) {
        // const delta = camera.parallelScale - previousCamera.parallelScale;
        const zoom = state.viewport.getZoom();
        proxy.emitter.emit("syncZoom", { zoom, pos: props.pos });
    }

    if (isCurrent && appStore.syncOperation.syncPan) {
        const pan = state.viewport.getPan();
        proxy.emitter.emit("syncPan", { pan, pos: props.pos });
    }

};

const onVoiModified = (event) => {
    if (!appStore.currentDisplayer) return;

    const isCurrent = (appStore.currentDisplayer.getViewportId() === viewportId);
    // console.log("onVoiModified", isCurrent, event);
    if (isCurrent && appStore.syncOperation.syncWindow) {
        proxy.emitter.emit("syncWindow", { range: event.detail.range, pos: props.pos });
    }
};

const onStackNewImage = (event) => {

    const idx = state.viewport.getCurrentImageIdIndex();
    scrollbar.value.setPosition(idx);
    playbar?.value?.setCurrent(idx);
    state.preStackIndex = state.stackIndex;
    state.stackIndex = idx;

    const {imageId, image} = event.detail;
    const { windowCenter, windowWidth } = image;

    if (windowWidth<=1)
    {
        console.log("windowWidth<=1");
        const dcmImage = state.series.GetImageById(imageId);
        const { defWL, defWW } = dcmImage;
        const ww = defWW;
        const wl = defWL;

        const voiLutFunction = state.viewport.getProperties().VOILUTFunction;
        const newRange = csUtils.windowLevel.toLowHighRange(
            ww,
            wl,
            voiLutFunction
        );

        state.viewport.setProperties({
            voiRange: newRange,
            invert: false,
        });

        state.viewport.render();
    }

};


const isLoaded = () => {
    return state.series !== null && state.image !== null;
};

const clear = () => {
    if (state.image) {
        state.renderingEngine.disableElement(viewportId);
        displayer.value.style.cursor = "default";
    }
    state.series = null;
    state.image = null;
    state.imageIds = [];
    state.isSeries = false;

    orientation.top = "";
    orientation.bottom = "";
    orientation.left = "";
    orientation.right = "";

    // 安全地调用scrollbar方法
    if (scrollbar.value && scrollbar.value.clearPress) {
        scrollbar.value.clearPress();
    }
}

const removeAllMeasures = () => {
    removeViewportMeasures(state.viewport, state.image.imageId);
    state.viewport.render();
};

const setProperties = (props) => {
    if (!state.image) return;
    switch (props.name) {
        case "flipH":
            const { flipHorizontal } = state.viewport.getCamera();
            state.viewport.setCamera({ flipHorizontal: !flipHorizontal });
            break;
        case "flipV":
            const { flipVertical } = state.viewport.getCamera();
            state.viewport.setCamera({ flipVertical: !flipVertical });
            break;
        case "invert":
            const { invert } = state.viewport.getProperties();
            state.viewport.setProperties({ invert: !invert });
            break;
        case "rotate":
            const { rotation } = state.viewport.getViewPresentation();
            let newRotation = (rotation + props.value) % 360;
            if (newRotation < 0) {
                newRotation += 360;
            }
            // console.log("rotate", rotation, newRotation);
            state.viewport.setViewPresentation({ rotation: newRotation });
            break;
    }

    state.viewport.render();
};

const setColorMap = (colorMap) => {
    if (!colorMap) {
        const { colormap } = state.viewport.getProperties();
        if (colormap) {
            state.viewport.resetProperties();
        }
    } else {
        state.viewport.setProperties({ colormap: { name: colorMap } });
    }
    state.viewport.render();
};

const resetCamera = () => {
    if (!state.image) return;
    state.viewport.resetCamera();
    const { colormap } = state.viewport.getProperties();
    if (colormap) {
        state.viewport.resetProperties();
    }
    const { defWL, defWW } = state.image;
    setWindow(defWL, defWW);
    state.viewport.render();
};

const getViewportId = () => {
    return viewportId;
};

const getImageIds = () => {
    return state.imageIds;
};

const render = () => {
    state.viewport.render();
};

const setWindow = (wl, ww) => {
    if (!state.image) return;

    const voiLutFunction = state.viewport.getProperties().VOILUTFunction;
    const newRange = csUtils.windowLevel.toLowHighRange(
        ww,
        wl,
        voiLutFunction
    );

    // console.log("setWindow", voiLutFunction, newRange);

    state.viewport.setProperties({
        voiRange: newRange,
    });

    state.viewport.render();
};

const getWindow = () => {
    if (!state.image) return;

    const range = state.viewport.getProperties().voiRange;
    return csUtils.windowLevel.toWindowLevel(range.lower, range.upper);
}

const setDefaultWindow = () => {
    if (!state.image) return;
    const { defWL, defWW } = state.image;
    setWindow(defWL, defWW);
};

const setVoiRange = (newRange) => {
    if (!state.image) return;
    state.viewport.setProperties({
        voiRange: newRange,
    });

    state.viewport.render();
};

const setZoom = (zoom) => {
    if (!state.image) return;

    state.viewport.setZoom(zoom);
    state.viewport.render();
};

const setPan = (pan) => {
    if (!state.image) return;

    state.viewport.setPan(pan);
    state.viewport.render();
};

const stopAutoPlay = () => {
    if (!state.image) return;
    playbar.value.stop();
};

const getTagList = async () => {
    if (!state.image) return [];
    return state.image.readTagList();
}

const showMenu = (e) => {
    // const rect = displayer.value.getBoundingClientRect();
    // console.log("showMenu", e.clientX, e.clientY, rect);
    // xMenu.value.show(menuList.value, { left: e.clientX-rect.x, top: e.clientY-rect.y });
};

const hideMenu = () => {
    xMenu.value.hide();
};

defineExpose({
    setSelected,
    load,
    isLoaded,
    clear,
    removeAllMeasures,
    setProperties,
    setColorMap,
    resetCamera,
    getViewportId,
    getImageIds,
    render,
    setWindow,
    getWindow,
    setDefaultWindow,
    setVoiRange,
    setZoom,
    setPan,
    stopAutoPlay,
    getTagList,
});

onMounted(() => {
    // console.log("Displayer onMounted");
    resizeObserver.observe(displayer.value);

    displayer.value.addEventListener(IMAGE_RENDERED, onImageRendered);
    displayer.value.addEventListener(CAMERA_MODIFIED, onCameraModified);
    displayer.value.addEventListener(VOI_MODIFIED, onVoiModified);
    displayer.value.addEventListener(STACK_NEW_IMAGE, onStackNewImage);

    // 添加全局拖放事件监听 - 只有当前选中的显示区域才处理
    window.addEventListener('seriesDrop', (e) => {
        // 只有当前选中的显示区域才处理拖放事件
        if (IsSel.value) {
            const seriesInsUid = e.detail.seriesInsUid;
            const series = archiveData.currentStudy.FindSeries(seriesInsUid);
            if (series) {
                load(series, 0, true);
            }
        }
    });

    // 添加移动端点击加载事件监听
    window.addEventListener('seriesLoad', (e) => {
        // 只有当前选中的显示区域才处理加载事件
        if (IsSel.value) {
            const seriesInsUid = e.detail.seriesInsUid;
            const series = archiveData.currentStudy.FindSeries(seriesInsUid);
            if (series) {
                load(series, 0, true);

                // 显示加载成功提示
                const successMsg = document.createElement('div');
                successMsg.style.position = 'fixed';
                successMsg.style.left = '50%';
                successMsg.style.top = '20%';
                successMsg.style.transform = 'translate(-50%, -50%)';
                successMsg.style.background = 'rgba(0, 128, 0, 0.8)';
                successMsg.style.color = 'white';
                successMsg.style.padding = '10px 20px';
                successMsg.style.borderRadius = '5px';
                successMsg.style.zIndex = '9999';
                successMsg.textContent = '序列加载成功！';
                document.body.appendChild(successMsg);

                setTimeout(() => {
                    if (document.body.contains(successMsg)) {
                        document.body.removeChild(successMsg);
                    }
                }, 2000);

            } else {
                // 显示加载失败提示
                const errorMsg = document.createElement('div');
                errorMsg.style.position = 'fixed';
                errorMsg.style.left = '50%';
                errorMsg.style.top = '20%';
                errorMsg.style.transform = 'translate(-50%, -50%)';
                errorMsg.style.background = 'rgba(255, 0, 0, 0.8)';
                errorMsg.style.color = 'white';
                errorMsg.style.padding = '10px 20px';
                errorMsg.style.borderRadius = '5px';
                errorMsg.style.zIndex = '9999';
                errorMsg.textContent = '序列加载失败！';
                document.body.appendChild(errorMsg);

                setTimeout(() => {
                    if (document.body.contains(errorMsg)) {
                        document.body.removeChild(errorMsg);
                    }
                }, 2000);
            }
        }
    });

});

onBeforeUnmount(() => {
    // console.log("onBeforeUnmount");
    if (state.image) {
        state.renderingEngine.disableElement(viewportId);
        toolGroup.removeViewports(renderingEngineId2d, viewportId);
    }

    displayer.value.removeEventListener(IMAGE_RENDERED, onImageRendered);
    displayer.value.removeEventListener(CAMERA_MODIFIED, onCameraModified);
    displayer.value.removeEventListener(VOI_MODIFIED, onVoiModified);
    displayer.value.removeEventListener(STACK_NEW_IMAGE, onStackNewImage);
    resizeObserver.unobserve(displayer.value);

    // 移除全局拖放事件监听
    window.removeEventListener('seriesDrop', (e) => {
        // 只有当前选中的显示区域才处理拖放事件
        if (IsSel.value) {
            const seriesInsUid = e.detail.seriesInsUid;
            const series = archiveData.currentStudy.FindSeries(seriesInsUid);
            if (series) {
                load(series, 0, true);
            }
        }
    });

    // 移除移动端点击加载事件监听
    window.removeEventListener('seriesLoad', (e) => {
        // 只有当前选中的显示区域才处理加载事件
        if (IsSel.value) {
            const seriesInsUid = e.detail.seriesInsUid;
            const series = archiveData.currentStudy.FindSeries(seriesInsUid);
            if (series) {
                load(series, 0, true);
            }
        }
    });
});
</script>

<template>
	<div
		class="displaybox"
		:class="borderClass"
		@drop.prevent="dragDrop($event)"
		@dragover.prevent
		@mousedown="onMouseDown"
		@mouseover="onMouseOver"
		@mouseout="onMouseOut"
		@mouseup="onMouseUp"
		@contextmenu.prevent="showMenu"
		@touchstart="handleTouchStart"
		@touchmove="handleTouchMove"
		@touchend="handleTouchEnd"
	>
		<XMenu ref="xMenu" @mouseleave="hideMenu" />
		<div class="displayer" ref="displayer" @mousemove="mouseMove">
			<span class="orient_top" v-show="appStore.showOrientText">{{
				orientation.top
			}}</span>
			<span class="orient_bottom" v-show="appStore.showOrientText">{{
				orientation.bottom
			}}</span>
			<span class="orient_left" v-show="appStore.showOrientText">{{
				orientation.left
			}}</span>
			<span class="orient_right" v-show="appStore.showOrientText">{{
				orientation.right
			}}</span>
		</div>
		<div class="scroll-right" v-show="isLoaded()">
			<VerticalScrollbar
				ref="scrollbar"
				:min="minPos"
				:max="maxPos"
				:size="10"
				@position="scrollTo"
			/>
		</div>
		<transition name="fade">
			<div
				class="animated-playbar"
				v-show="showPlaybar"
				@mouseleave="mouseOutPlaybar"
			>
				<Playbar
					ref="playbar"
					:max="maxPos"
					@changeValue="scrollTo"
					@startPlay="startPlay"
				/>
			</div>
		</transition>
	</div>
</template>
<style lang="scss" scoped>
$font-size: 14px;
@mixin orient($text-align: left) {
	position: absolute;
	color: white;
	font-size: $font-size;
	text-align: $text-align;
	user-select: none;
	z-index: 10;
}

.displaybox {
	position: relative;
	display: flex;
	flex-direction: row;
	background-color: black;
	overflow: hidden;
}

.displayer {
	position: relative;
	flex: 1;
	text-align: left;
	cursor: default;
	user-select: none;
}
.scroll-right {
	width: 10px;
	height: 100%;
}

.scroll-bottom {
	width: 100%;
	height: 10px;
}

.orient_top {
	@include orient(center);
	top: 2px;
	left: calc(50% - 30px);
	width: 60px;
}

.orient_bottom {
	@include orient(center);
	bottom: 2px;
	left: calc(50% - 30px);
	width: 60px;
}

.orient_left {
	@include orient();
	top: calc(50% - 20px);
	left: 2px;
}

.orient_right {
	@include orient();
	top: calc(50% - 20px);
	right: 4px;
}

.selected {
	border: 1px solid red;
}
.hovered {
	border: 1px dashed yellow;
}
.unselect {
	border: 1px solid #fff;
}

.animated-playbar {
	position: absolute;
	display: flex;
	justify-content: center;
	width: 100%;
	height: 32px;
	bottom: 20px;
	left: 0;
	z-index: 11;
}

.fade-enter-active {
	transition: opacity 0.2s ease;
}
.fade-leave-active {
	transition: opacity 0.6s ease;
}

.fade-enter, .fade-leave-to /* .fade-leave-active below version 2.1.8 */ {
	opacity: 0;
}
</style>
